package cn.lumin.mock.service;

import cn.lumin.mock.config.LuminConfiguration;
import cn.lumin.mock.domain.BidData;
import cn.lumin.mock.domain.ExecutionInfo;
import cn.lumin.mock.domain.PriceData;
import cn.lumin.mock.dto.BidDataDTO;
import cn.lumin.mock.dto.ExecutionInfoDTO;
import cn.lumin.mock.dto.PriceDataDTO;

import com.cutefool.dsl.mybatis.core.dsl.builder.InsertDsl;
import com.cutefool.dsl.mybatis.core.dsl.builder.QueryDsl;
import com.cutefool.dsl.mybatis.core.dsl.operation.CuteCurdOperation;
import com.mysql.cj.x.protobuf.MysqlxCrud.Insert;

import jakarta.annotation.Resource;

import org.mybatis.dynamic.sql.insert.InsertDSL;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.math.RoundingMode;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.util.List;
import java.util.Random;
import java.util.UUID;

@Service
public class DataGenerationService {

    @Resource
    private CuteCurdOperation<Long, BidData> bidDataOperation;

    @Resource
    private CuteCurdOperation<Long, ExecutionInfo> executionInfoOperation;

    @Resource
    private CuteCurdOperation<Long, PriceData> priceDataOperation;

    @Resource
    private LuminConfiguration luminConfiguration;

    private final Random random = new Random();

    /**
     * 生成当日数据到三个表
     */
    public void generateTodayData() {
        LocalDate today = LocalDate.now();

        // 生成申报单数据
        generateBidData(today);

        // 生成成交信息数据
        generateExecutionInfo(today);

        // 生成电价数据
        generatePriceData(today);
    }

    /**
     * 生成申报单数据
     */
    private void generateBidData(LocalDate targetDate) {
        // 从配置中获取交易单元信息
        List<LuminConfiguration.TradingUnit> tradingUnits = luminConfiguration.getTradingUnits();

        for (int timeCode = 1; timeCode <= 24; timeCode++) {
            for (LuminConfiguration.TradingUnit tradingUnit : tradingUnits) {
                BidDataDTO bidDataDTO = new BidDataDTO();
                bidDataDTO.setId(generateId());
                bidDataDTO.setTradingUnit(tradingUnit.getName());
                bidDataDTO.setTradingUnitId(tradingUnit.getId());
                bidDataDTO.setTargetDate(targetDate);
                bidDataDTO.setTradingDate(targetDate);
                bidDataDTO.setTimeCode((byte) timeCode);
                bidDataDTO.setOrderStatus((byte) (random.nextInt(3))); // 0-2
                bidDataDTO.setTradingStatus((byte) (random.nextInt(4))); // 0-3
                bidDataDTO.setDeclaredQuantity(new BigDecimal(random.nextInt(1000) + 100).setScale(4, RoundingMode.HALF_UP));
                bidDataDTO.setDeclaredPrice(new BigDecimal(random.nextInt(500) + 200).setScale(4, RoundingMode.HALF_UP));
                bidDataDTO.setTradingDirection((byte) (random.nextInt(2) + 1)); // 1-2
                bidDataDTO.setSupervisionDirection((byte) (random.nextInt(2) + 1)); // 1-2
                bidDataDTO.setEffectiveAmount(new BigDecimal(random.nextInt(500) + 50).setScale(4, RoundingMode.HALF_UP));
                bidDataDTO.setSupervisionPrice(new BigDecimal(random.nextInt(600) + 250).setScale(4, RoundingMode.HALF_UP));
                bidDataDTO.setRemark("时段" + timeCode + "申报数据");
                bidDataDTO.setTenantId("000000");
                bidDataDTO.setCreateDept(1L);
                bidDataDTO.setCreateTime(LocalDateTime.now());
                bidDataDTO.setCreateBy(1L);
                bidDataDTO.setUpdateTime(LocalDateTime.now());
                bidDataDTO.setUpdateBy(1L);
                bidDataDTO.setOrgCode(luminConfiguration.getOrgCode());
                bidDataDTO.setBidDate(targetDate);
                InsertDsl<Long,BidData> insertDsl = InsertDsl.newInstance(BidData.instance()).entity(bidDataDTO);
                this.bidDataOperation.create(insertDsl);
            }
        }
    }

    /**
     * 生成成交信息数据
     */
    private void generateExecutionInfo(LocalDate targetDate) {
        // 从配置中获取交易单元信息
        List<LuminConfiguration.TradingUnit> tradingUnits = luminConfiguration.getTradingUnits();
        String[] tradingDirections = {"买", "卖"};

        for (int timeCode = 1; timeCode <= 24; timeCode++) {
            for (LuminConfiguration.TradingUnit tradingUnit : tradingUnits) {
                ExecutionInfoDTO executionInfoDTO = new ExecutionInfoDTO();
                executionInfoDTO.setId(generateId());
                executionInfoDTO.setTradingUnit(tradingUnit.getName());
                executionInfoDTO.setTradingUnitId(tradingUnit.getId());
                executionInfoDTO.setMarketId("MARKET001");
                executionInfoDTO.setTargetDate(targetDate);
                executionInfoDTO.setTimeCode((byte) timeCode);
                executionInfoDTO.setTradingDirection(tradingDirections[random.nextInt(tradingDirections.length)]);
                executionInfoDTO.setDealPrice(new BigDecimal(random.nextInt(400) + 200).setScale(4, BigDecimal.ROUND_HALF_UP));
                executionInfoDTO.setDealEnergy(new BigDecimal(random.nextInt(800) + 200).setScale(4, BigDecimal.ROUND_HALF_UP));

                // 设置申报时间和成交时间
                LocalDateTime bidTime = LocalDateTime.of(targetDate, LocalTime.of(timeCode - 1, random.nextInt(60)));
                LocalDateTime dealTime = bidTime.plusMinutes(random.nextInt(30) + 5);
                executionInfoDTO.setBidTime(bidTime);
                executionInfoDTO.setDealTime(dealTime);

                executionInfoDTO.setBidPrice(new BigDecimal(random.nextInt(450) + 180).setScale(4, BigDecimal.ROUND_HALF_UP));
                executionInfoDTO.setBidEnergy(new BigDecimal(random.nextInt(900) + 150).setScale(4, BigDecimal.ROUND_HALF_UP));
                executionInfoDTO.setVenListingId("VEN" + UUID.randomUUID().toString().substring(0, 8).toUpperCase());
                executionInfoDTO.setSaleListingId("SALE" + UUID.randomUUID().toString().substring(0, 8).toUpperCase());
                executionInfoDTO.setTenantId("000000");
                executionInfoDTO.setCreateDept(1L);
                executionInfoDTO.setCreateTime(LocalDateTime.now());
                executionInfoDTO.setCreateBy(1L);
                executionInfoDTO.setUpdateTime(LocalDateTime.now());
                executionInfoDTO.setUpdateBy(1L);
                executionInfoDTO.setOrgCode(luminConfiguration.getOrgCode());
                executionInfoDTO.setTradingDate(targetDate);
                executionInfoDTO.setGuid(UUID.randomUUID().toString());

                InsertDsl<Long,ExecutionInfo> insertDsl = InsertDsl.newInstance(ExecutionInfo.instance()).entity(executionInfoDTO);
                this.executionInfoOperation.create(insertDsl);
            }
        }
    }

    /**
     * 生成电价数据
     */
    private void generatePriceData(LocalDate targetDate) {
        // 价格类型列表
        Integer[] priceTypes = {1, 2, 3, 4, 5, 6, 7, 100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110, 111, 112, 113, 114, 115};

        for (int timeCode = 1; timeCode <= 24; timeCode++) {
            for (Integer priceType : priceTypes) {
                PriceDataDTO priceDataDTO = new PriceDataDTO();
                priceDataDTO.setId(generateId());
                priceDataDTO.setPriceType(priceType);

                // 设置电价时间
                LocalDateTime priceDateTime = LocalDateTime.of(targetDate, LocalTime.of(timeCode - 1, 0));
                priceDataDTO.setDate(priceDateTime);

                // 根据价格类型生成不同的电价
                BigDecimal basePrice = new BigDecimal(200);
                switch (priceType) {
                    case 1: // 预测日前价格
                    case 2: // 实际日前价格
                        basePrice = new BigDecimal(220);
                        break;
                    case 3: // 实际实时价格
                    case 4: // 预测实时价格
                        basePrice = new BigDecimal(240);
                        break;
                    case 100: // 日前江南分区价格
                    case 101: // 日前江北分区价格
                        basePrice = new BigDecimal(230);
                        break;
                    case 104: // 实时江南分区价格
                    case 105: // 实时江北分区价格
                        basePrice = new BigDecimal(250);
                        break;
                    default:
                        basePrice = new BigDecimal(200 + random.nextInt(100));
                }

                // 添加随机波动
                BigDecimal variation = new BigDecimal(random.nextInt(40) - 20);
                priceDataDTO.setValue(basePrice.add(variation).setScale(4, BigDecimal.ROUND_HALF_UP));

                priceDataDTO.setBizDate(targetDate.toString());
                priceDataDTO.setSource("MOCK_V1.0");
                priceDataDTO.setCreateDept(1L);
                priceDataDTO.setCreateTime(LocalDateTime.now());
                priceDataDTO.setUpdateTime(LocalDateTime.now());
                priceDataDTO.setTenantId("000000");
                priceDataDTO.setOrgCode(luminConfiguration.getOrgCode());
                priceDataDTO.setDayAheadPriceLagHours(24);
                priceDataDTO.setRealTimePriceLagHours(1);
                priceDataDTO.setRealTimeExogLagHours(2);

                InsertDsl<Long,PriceData> insertDsl = InsertDsl.newInstance(PriceData.instance()).entity(priceDataDTO);
                this.priceDataOperation.create(insertDsl);
            }
        }
    }

    /**
     * 生成唯一ID
     */
    private Long generateId() {
        return System.currentTimeMillis() + random.nextInt(1000);
    }
}
